﻿using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Net;
using System.Web.Mvc;
using Mondial2014.Models.Context;
using Mondial2014.Models.Gambling;

namespace Mondial2014.Controllers
{
    public class KnockoutGamblesController : Controller
    {
        private readonly Mondial2014DbContext m_Context = new Mondial2014DbContext();

        public class KnockoutGambleViewModel
        {
            public int GamblerId { get; set; }
            public string GamblerName { get; set; }
            public int GambleId { get; set; }
            public int TeamId { get; set; }
            public string TeamName { get; set; }
        }

        // GET: KnockoutGambles
        public ActionResult Index(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            var gambler = m_Context.Gamblers.Find(id);
            if (gambler == null)
            {
                return HttpNotFound();
            }

            AddGambles(gambler);

            return View(GetKnockoutGambleViewModels(gambler.Id));
        }

        [HttpPost]
        public ActionResult Index(List<KnockoutGambleViewModel> knockoutGambleViewModels)
        {
            if (ModelState.IsValid)
            {
                var gamblerId = knockoutGambleViewModels.First().GamblerId;
                var index = 0;
                foreach (var knockoutGambleId in GetKnockoutGambles(gamblerId)
                                                    .Select(g => g.Id)
                                                    .ToArray())
                {
                    var gambleId = knockoutGambleId;
                    var teamId = knockoutGambleViewModels[index].TeamId;
                    var knockoutGamble = m_Context.KnockoutGambles.Single(g => g.Id == gambleId);
                    var team = m_Context.Teams.Single(t => t.Id == teamId);
                    knockoutGamble.Team = team;
                    index++;
                }

                m_Context.SaveChanges();

                return RedirectToAction("Index", "Gamblers", new { id = knockoutGambleViewModels.First().GamblerId });
            }
            return View(knockoutGambleViewModels);
        }

        private List<KnockoutGambleViewModel> GetKnockoutGambleViewModels(int gamblerId)
        {
            var list = 
                GetKnockoutGambles(gamblerId)
                .Select(gamble => new KnockoutGambleViewModel
                    {
                        GamblerId = gamble.Gambler.Id,
                        GamblerName = gamble.Gambler.Name,
                        GambleId = gamble.Id
                    })
                .ToList();
            foreach (var knockoutGambleViewModel in list)
            {
                var team = m_Context.KnockoutGambles.Include(g => g.Team).Single(g => g.Id == knockoutGambleViewModel.GambleId).Team;
                knockoutGambleViewModel.TeamId = (team == null) ? 0 : team.Id;
                knockoutGambleViewModel.TeamName = (team == null) ? "" : team.Name;
            }
            return list;
        }

        private void AddGambles(Gambler gamber)
        {
            if (!m_Context.KnockoutGambles.Any(g => g.Gambler.Id == gamber.Id))
            {
                for (var level = 1; level < 6; level++)
                {
                    var stage = m_Context.Stages.Single(s => s.Level == level);

                    for (var team = 0; team < Math.Pow(2, 5 - level); team++)
                    {
                        m_Context.KnockoutGambles.Add(new KnockoutGamble
                        {
                            Gambler = gamber,
                            Stage = stage
                        });
                    }
                }
                m_Context.SaveChanges();
            }

            // workaround for a bug of mine... can be removed once all gambles in production are set
            if (!m_Context.KnockoutGambles.Any(g => g.Gambler.Id == gamber.Id && g.Stage.Level == 5))
            {
                m_Context.KnockoutGambles.Add(new KnockoutGamble
                {
                    Gambler = gamber,
                    Stage = m_Context.Stages.Single(s => s.Level == 5)
                });
                m_Context.SaveChanges();
            }
        }

        private IEnumerable<KnockoutGamble> GetKnockoutGambles(int gamblerId)
        {
            return m_Context.KnockoutGambles
                .Where(k => k.Gambler.Id == gamblerId)
                .OrderBy(g => g.Stage.Level)
                .ThenBy(g => g.Id);
        }
    }
}